using System;
using System.Linq;
using System.Windows;
using System.Windows.Interop;
using Jacobi.Vst.Core;
using Jacobi.Vst.Interop.Host;
using Play.Shell.Views;
using Play.VstPluginManagement;
using PortAudioSharp;

namespace Play.AudioEngine
{
	public class PortAudioVstPlayback
	{
		private readonly AudioRack _audioRack;
		private readonly Audio _audio;

		public PortAudioVstPlayback(AudioRack audioRack)
		{
			_audioRack = audioRack;

			_audio = new Audio(
				AudioParameters.NbChannels,
				AudioParameters.NbChannels,
				AudioParameters.SampleRate,
				AudioParameters.BlockSize,
				AudioCallback);
			
			Play();
		}

		private int _i = 0;

		private PortAudio.PaStreamCallbackResult AudioCallback(
			IntPtr audioInputBuffer, IntPtr audioOutputBuffer, 
			uint blockSize,
			ref PortAudio.PaStreamCallbackTimeInfo timeInfo,
			PortAudio.PaStreamCallbackFlags statusFlags,
			IntPtr userData)
		{
			var channels = _audioRack.GetChannelsCopy().ToList();

			if (_i == 1000)
			{
				channels.ForEach(it => it.ProcessMidi(
					new VstEvent[]
						{
							new VstMidiEvent(0, 0, 0, new byte[] { 144, 60, 100 }, 0, 110)
						}));
			}
			_i++;

			var outputBuffers = channels
				.AsParallel()
				.Select(it => it.ProcessAudio())
				.ToList();

			var i = 0;
			var j = 0;
			unsafe
			{
				// Fill audio buffer for all channels, multiply samples by volume range [0, 1]
				var audioBuffer = (float*)audioOutputBuffer.ToPointer();

				while (i < blockSize * AudioParameters.NbChannels)
				{
					for (var k = 0; k < AudioParameters.NbChannels; k++)
					{
						var value = 0f;
						for (var l = 0; l < outputBuffers.Count; l++)
							value += outputBuffers[l][k][j] * 0.3f;
						
						audioBuffer[i++] = value;
					}
					j++;
				}
			}

			return PortAudio.PaStreamCallbackResult.paContinue;
		}

		// TODO: Einbauen
		public void Play()
		{
			_audio.Start();
		}

		//public void Stop()
		//{
		//    _audio.Stop();
		//}
	}
}